package com.lujian.casual.benchmark;

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import java.util.concurrent.TimeUnit;

@State(Scope.Thread)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class BenchMarkCompilerControl {

    /*
     * We can use HotSpot-specific functionality to tell the compiler what
     * do we want to do with particular methods. To demonstrate the effects,
     * we end up with 3 methods in this sample.
     */

        /**
         * These are our targets:
         *   - first method is prohibited from inlining
         *   - second method is forced to inline
         *   - third method is prohibited from compiling
         *
         * We might even place the annotations directly to the benchmarked
         * methods, but this expresses the intent more clearly.
         */

        public void target_blank() {
            // this method was intentionally left blank
        }

        @CompilerControl(CompilerControl.Mode.DONT_INLINE)
        public void target_dontInline() {
            // this method was intentionally left blank
        }

        @CompilerControl(CompilerControl.Mode.INLINE)
        public void target_inline() {
            // this method was intentionally left blank
        }

        @CompilerControl(CompilerControl.Mode.EXCLUDE)
        public void target_exclude() {
            // this method was intentionally left blank
        }

    /*
     * These method measures the calls performance.
     */

        @Benchmark
        public void baseline() {
            // this method was intentionally left blank
        }

        @Benchmark
        public void blank() {
            target_blank();
        }

        @Benchmark
        public void dontinline() {
            target_dontInline();
        }

        @Benchmark
        public void inline() {
            target_inline();
        }

        @Benchmark
        public void exclude() {
            target_exclude();
        }

    /*
     * ============================== HOW TO RUN THIS TEST: ====================================
     *
     * Note the performance of the baseline, blank, and inline methods are the same.
     * dontinline differs a bit, because we are making the proper call.
     * exclude is severely slower, becase we are not compiling it at all.
     *
     * You can run this test:
     *
     * a) Via the command line:
     *    $ mvn clean install
     *    $ java -jar target/benchmarks.jar JMHSample_16 -wi 1 -i 3 -f 1
     *    (we requested 1 warmup iterations, 3 iterations, single fork)
     *
     * b) Via the Java API:
     *    (see the JMH homepage for possible caveats when running from IDE:
     *      http://openjdk.java.net/projects/code-tools/jmh/)
     */

        public static void main(String[] args) throws RunnerException {
            Options opt = new OptionsBuilder()
                    .include(BenchMarkCompilerControl.class.getSimpleName())
                    .warmupIterations(1)
                    .measurementIterations(3)
                    .forks(1)
                    .build();

            new Runner(opt).run();
        }

}
